﻿#include "parsehex.h"

ParseHex::ParseHex()
{
    const uchar data_begin[] = { 0xff, 0x00, 0xaa, 0x55, 0xcc, 0x00, 0xdd, 0xee };
    flash_data = QByteArray::fromRawData((const char*)data_begin, sizeof(data_begin));
    flash_data.append(8, 0x0f);

    const uchar data_end[] = { 0xcc, 0x00, 0xdd, 0xee, 0xff, 0x00, 0xaa, 0x55 };
    flash_end_data = QByteArray::fromRawData((const char*)data_end, sizeof(data_end));
    flash_end_data.append(48, 0xf0);
    //    const uchar data_begin[] = {0x13, 0x01, 0x00, 0x08};
    //    bin_data = QByteArray::fromRawData((const char *)data_begin, sizeof(data_begin));
    //    bin_data.append(bin_data);
    //    bin_data.append(bin_data);
    //    bin_data.append(bin_data);
    //    qDebug() << bin_data.toHex(' ');
}

void ParseHex::clear()
{
    ExStageAddr = 0x00;
    ExLineAddr = 0x00;
    absoluteAddrLocal = 0x00;
    bin_data.clear();
    flash_data.truncate(16);
    // bin_data.truncate(16);
}

bool ParseHex::parse(QString fileName)
{
    QByteArray text_hex, data_hex;

    if (fileName.isEmpty())
        return false;

    QFile hexfile(fileName);
    if (!hexfile.open(QIODevice::ReadOnly)) {
        error_info = "打开文件失败";
        return false;
    }
    bool parse_hex = false;
    text_hex.fill(0x00, 128 * 1024 - 16);
    while (!hexfile.atEnd()) { // 循环处理，至hex文件读完
        /*若： alinedata =QByteArray::fromHex(":12345678");
          则： alinedara ={0x12,0x23,0x45,0x78};*/
        QByteArray alinedata = QByteArray::fromHex(hexfile.readLine()); // 从hex文件中读取一行
        if (alinedata.isEmpty())
            continue;
        char ret = ReadHexLineData(alinedata, text_hex, data_hex); // 将一行数据解读到HexDataStr结构体
        if (ret == 2) {
            parse_hex = false;
            break;
        } else if (ret == 1) {
            parse_hex = true;
            break;
        } else {
            parse_hex = true;
        }
    }
    hexfile.close();
    QFile out3_file("out3_bin.txt");
    out3_file.open(QIODevice::WriteOnly | QIODevice::Text);
    out3_file.write(text_hex.toHex(' '));
    out3_file.close();
    bin_data = text_hex;

    QByteArray temp(4, 0);
    for (int i = 0; i < bin_data.size(); i += 8) {
        // 12 34 56 78 9a bc de ff
        // ff de bc 9a 78 56 34 12
        temp[0] = bin_data[i];
        temp[1] = bin_data[i + 1];
        temp[2] = bin_data[i + 2];
        temp[3] = bin_data[i + 3];

        bin_data[i] = bin_data[i + 7];
        bin_data[i + 1] = bin_data[i + 6];
        bin_data[i + 2] = bin_data[i + 5];
        bin_data[i + 3] = bin_data[i + 4];

        bin_data[i + 7] = temp[0];
        bin_data[i + 6] = temp[1];
        bin_data[i + 5] = temp[2];
        bin_data[i + 4] = temp[3];
    }
    flash_data.append(bin_data);

    //    if(parse_hex)
    //    {
    //        data_hex = data_hex.right(data_hex.size() - 16);
    //        qDebug() << "text_hex:" << text_hex.size() << "|data_hex:" << data_hex.size();
    //        if(data_hex.size() <= 32*1024)
    //        {
    //            if(text_hex.size() > 32*3*1024)
    //            {
    //                error_info = "文件超过128K!";
    //                return false;
    //            }
    //            bin_data.append(text_hex);
    //            bin_data.append(32*3*1024-text_hex.size(), 0x00);
    //            bin_data.append(data_hex);
    //            bin_data.append(32*1024-data_hex.size(), 0x00);
    //        }
    //        else if(data_hex.size() <= 32*2*1024)
    //        {
    //            if(text_hex.size() > 32*2*1024)
    //            {
    //                error_info = "文件超过128K!";
    //                return false;
    //            }
    //            bin_data.append(text_hex);
    //            bin_data.append(32*2*1024-text_hex.size(), 0x00);
    //            bin_data.append(data_hex);
    //            bin_data.append(32*2*1024-data_hex.size(), 0x00);
    //        }
    //        else if(data_hex.size() <= 32*3*1024)
    //        {
    //            if(text_hex.size() > 32*1*1024)
    //            {
    //                error_info = "文件超过128K!";
    //                return false;
    //            }
    //            bin_data.append(text_hex);
    //            bin_data.append(32*1*1024-text_hex.size(), 0x00);
    //            bin_data.append(data_hex);
    //            bin_data.append(32*3*1024-data_hex.size(), 0x00);
    //        }
    //        else
    //        {
    //            error_info = "文件超过128K!";
    //            return false;
    //        }

    //        QByteArray temp(4, 0);
    //        bin_data.truncate(128*1024-16);
    //        for(int i=0; i < bin_data.size(); i+=8)
    //        {
    //            //12 34 56 78 9a bc de ff
    //            //ff de bc 9a 78 56 34 12
    //            temp[0] = bin_data[i];
    //            temp[1] = bin_data[i+1];
    //            temp[2] = bin_data[i+2];
    //            temp[3] = bin_data[i+3];

    //            bin_data[i] = bin_data[i+7];
    //            bin_data[i+1] = bin_data[i+6];
    //            bin_data[i+2] = bin_data[i+5];
    //            bin_data[i+3] = bin_data[i+4];

    //            bin_data[i+7] = temp[0];
    //            bin_data[i+6] = temp[1];
    //            bin_data[i+5] = temp[2];
    //            bin_data[i+4] = temp[3];
    //        }
    //        flash_data.append(bin_data);
    //    }
    return parse_hex;
}

char ParseHex::ReadHexLineData(const QByteArray& ba, QByteArray& out, QByteArray& out2) // return 0: ok  1:hex文件结束 2：hex文件有误
{
    HexFormatForLine hex_data;
    unsigned char i, checkoutCal = 0;

    // 计算校验值
    for (i = 0; i < ba.size() - 1; i++) {
        checkoutCal += (unsigned char)ba.at(i);
    }
    checkoutCal = 0x100 - checkoutCal;
    // 获取个部分域的值
    hex_data.datalen = (unsigned char)ba.at(0);
    hex_data.addr = ((unsigned char)ba.at(1) << 8) | (unsigned char)ba.at(2);
    hex_data.datatype = (unsigned char)ba.at(3);
    memset(hex_data.databuf, 0, sizeof(hex_data.databuf));
    for (i = 0; i < hex_data.datalen; i++) {
        hex_data.databuf[i] = (unsigned char)ba.at(4 + i);
    }
    hex_data.checkout = (unsigned char)ba.at(4 + i);
#if 0 // 调试时打开
     qDebug("datalen=%X",hex_data.datalen);
     qDebug("addr=%X",hex_data.addr);
     qDebug("datatype=%X",hex_data.datatype);
     qDebug("checkout=%X",hex_data.checkout);
     qDebug("checkoutCal=%X",checkoutCal);
#endif
    // 比较读取的校验值和计算的校验值是否一致
    if (checkoutCal != hex_data.checkout) {
        qDebug("校验出错,hex文件有误.");
        return 2;
    }
    return HexToBin2(&hex_data, out);
}

char ParseHex::HexToBin2(HexFormatForLine* ba, QByteArray& out3) // return 0: ok  1:hex文件结束 2：hex文件有误
{
    unsigned int absoluteAddrCurrent = 0x00; // 计算当前记录的绝对地址
    unsigned int Bytesskipped = 0; // 被跳过的字节数

    switch (ba->datatype) {
    case 0x00: // 数据记录
               // 计算出当前记录的绝对地址
        absoluteAddrCurrent = (ba->addr + ExStageAddr);

        break;
    case 0x01: // 文件结束记录
        return 1;
        break;
    case 0x02: // 扩展段地址记录
        ExStageAddr = (ba->databuf[0] << 8 | ba->databuf[1]) << 4;
        return 0; // return ok
        break;
    case 0x04: // 扩展线性地址记录
        ExStageAddr = (ba->databuf[0] << 8 | ba->databuf[1]) << 16;
        return 0; // return ok
        break;
    case 0x03: // 开始段地址记录
        // ExStageAddr = (ba->databuf[0]<<8|ba->databuf[1])<<2;
        // ExLineAddr = 0x00;
        return 0; // return ok
        break;
    default:
        return 2;
        break;
    }
    // out3  should be 128k-16 byte all zreo at initial state;
    if (absoluteAddrCurrent >= 0x00018000 && absoluteAddrCurrent < 0x20000000)
        return 2;
    if (absoluteAddrCurrent >= 0x20018000)
        return 2;
    if (absoluteAddrCurrent < 0x00000010)
        return 2;

    if (absoluteAddrCurrent >= 0x00000010 && absoluteAddrCurrent < 0x00018000) {
        for (unsigned int i = 0; i < ba->datalen; i++) {
            out3[absoluteAddrCurrent - 0x10 + i] = (ba->databuf[i]);
        }
        if (absoluteAddrCurrent >= 0x00000000 && absoluteAddrCurrent < 0x00008000)
            absoluteAddrLocal |= 0x1;
        if (absoluteAddrCurrent >= 0x00008000 && absoluteAddrCurrent < 0x00010000)
            absoluteAddrLocal |= 0x3;
        if (absoluteAddrCurrent >= 0x00010000 && absoluteAddrCurrent < 0x00018000)
            absoluteAddrLocal |= 0x7;
    } else if (absoluteAddrCurrent >= 0x20000000 && absoluteAddrCurrent < 0x20008000) {

        for (unsigned int i = 0; i < ba->datalen; i++) {
            out3[absoluteAddrCurrent - 0x20000010 + 0x18000 + i] = (ba->databuf[i]);
        }
    } else if (absoluteAddrCurrent >= 0x20008000 && absoluteAddrCurrent < 0x20010000) {
        if (absoluteAddrLocal & 0x4)
            return 2;
        for (unsigned int i = 0; i < ba->datalen; i++) {
            out3[absoluteAddrCurrent - 0x20000010 + 0x8000 + i] = (ba->databuf[i]);
        }

    } else if (absoluteAddrCurrent >= 0x20010000 && absoluteAddrCurrent < 0x20018000) {
        if (absoluteAddrLocal & 0x6)
            return 2;

        for (unsigned int i = 0; i < ba->datalen; i++) {
            out3[absoluteAddrCurrent - 0x20000010 - 0x8000 + i] = (ba->databuf[i]);
        }
    }

    return 0; // return ok
}
